﻿using HIWSystem.Attributes;
using HIWSystem.Helpers;
using HIWSystem.Models;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace HIWSystem.Common
{
    /// <summary>
    /// 机种类型
    /// </summary>
    public enum EnumPNType : int
    {
        Ant,   //天线
        Filter,//滤波器
        Ret,   //马达
        All    //所有
    }

    public enum EnumStationType : int
    {
        All,    //所有
        Normal, //正常站位《LPRINT/PACKING》
        QC,     //质量
        Test    //测试站位
    }

    public class BusinessProcess
    {
        private static SqlHelper sqlHelper = new SqlHelper();

        /// <summary>
        /// 返回登录的结果
        /// </summary>
        /// <param name="user">用户名</param>
        /// <param name="paw">密码</param>
        /// <returns></returns>
        public static string GetLogInResult(string user, string paw)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@User",SqlDbType.NVarChar,50),
                new SqlParameter("@Password",SqlDbType.NVarChar,100),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = user;
                sqlParameters[1].Value = MD5Helper.MD5Encrypt(paw);
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procVerifyLogIn", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 获取菜单项
        /// </summary>
        /// <returns></returns>
        public static DataTable GetMenuItems()
        {
            DataTable dt = new DataTable();
            string sql = string.Empty;//查询字符串
            try
            {
                sql = "select g.ParentHeader,g.ChildHeader Header,g.OwnerId,g.MenuItemLevel,g.MDId,h.Id,h.MenuCn from ( " +
                     "select e.ParentHeader,f.MDId,e.ChildHeader,e.OwnerId,e.MenuItemLevel from( " +
                     "select isnull(c.Header,'') ParentHeader,d.Header ChildHeader, d.OwnerId,d.MenuItemLevel from ClientMenuConfig c right join( " +
                     "select Header, OwnerId, MenuItemLevel from ClientMenuConfig where charindex(ActorLevel, (select Access from UserInfo where UserNo = '" + LogInInfo.User + "'))<> 0 group by Header, OwnerId,MenuItemLevel) d " +
                     "on c.MenuItemId = d.OwnerId) e left join ClientMenuConfig f on e.ChildHeader = f.Header) g left join MenuDefine h on g.MDId = h.Id";
                dt = sqlHelper.GetTable(sql);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 添加站位信息
        /// </summary>
        /// <param name="stationsEntity">站位实体类</param>
        /// <param name="dtStation">站位信息数据表</param>
        /// <returns></returns>
        public static string AddStation(StationsEntity stationsEntity, out DataTable dtStation)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@StationDesc",SqlDbType.NVarChar,300),
                new SqlParameter("@Type",SqlDbType.NVarChar,100),
                new SqlParameter("@PackingCheckFlag",SqlDbType.VarChar,1),
                new SqlParameter("@EndCheckFlag",SqlDbType.VarChar,1),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = stationsEntity.Station;
                sqlParameters[1].Value = stationsEntity.StationDesc;
                sqlParameters[2].Value = stationsEntity.StationType;
                sqlParameters[3].Value = stationsEntity.PackingCheckFlag;
                sqlParameters[4].Value = stationsEntity.EndCheckFlag;
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddStation", sqlParameters, out dtStation);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 删除站位信息
        /// </summary>
        /// <param name="sEntity">员工实体类</param>
        /// <returns></returns>
        public static bool DeleteStationInfo(StationsEntity sEntity)
        {
            StringBuilder sql = new StringBuilder();
            try
            {
                sql.AppendFormat("delete from Station where Id={0}", sEntity.Id);
                return sqlHelper.ExecuteNonQuery(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 更新站位信息
        /// </summary>
        /// <param name="entity">站位实体类</param>
        /// <returns></returns>
        public static string UpdateStationInfo(StationsEntity entity)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Station",SqlDbType.NVarChar,50),
                new SqlParameter("@Description",SqlDbType.NVarChar,300),
                new SqlParameter("@Type",SqlDbType.NVarChar,50),
                new SqlParameter("@PackingCheckFlag",SqlDbType.NVarChar,50),
                new SqlParameter("@EndCheckFlag",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000),
                };
                sqlParameters[0].Value = entity.Station ?? "";
                sqlParameters[1].Value = entity.StationDesc ?? "";
                sqlParameters[2].Value = entity.StationType ?? "";
                sqlParameters[3].Value = entity.PackingCheckFlag ?? "";
                sqlParameters[4].Value = entity.EndCheckFlag ?? "";
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procUpdateStation", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 返回系统中所有站位信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetStations(EnumStationType stationType)
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                switch (stationType)
                {
                    case EnumStationType.All:
                        sql.AppendFormat("select * from Station order by CreateAt");
                        break;

                    case EnumStationType.Normal:
                        sql.AppendFormat("select * from Station where Type='{0}' order by CreateAt", "Normal");
                        break;

                    case EnumStationType.QC:
                        sql.AppendFormat("select * from Station where Type='{0}' order by CreateAt", "QC");
                        break;

                    case EnumStationType.Test:
                        sql.AppendFormat("select * from Station where Type='{0}' order by CreateAt", "Test");
                        break;

                    default:
                        sql.AppendFormat("select * from Station order by CreateAt");
                        break;
                }
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取权限信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetMenuLevelInfo()
        {
            StringBuilder sql = new StringBuilder();//查询字符串
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select M.MenuEn,M.MenuCn,C.ActorLevel from [dbo].[ClientMenuConfig] C Inner join [dbo].[MenuDefine] M on c.MDId=m.Id order by C.ActorLevel");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取标签打印配置信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetLabelPrintConfigInfo()
        {
            StringBuilder sql = new StringBuilder();//查询字符串
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from LabelPrintConfig order by Id");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 自动生成下一个菜单权限字符
        /// </summary>
        /// <returns></returns>
        public static string AutoGenerateNextMenuLevel()
        {
            string newMenuLevel = string.Empty;
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                     {
                        new SqlParameter("@NewMenuLevel",SqlDbType.NVarChar,50),
                     };
                sqlParameters[0].Direction = ParameterDirection.Output;
                newMenuLevel = sqlHelper.ExecuteStoredProcedure("procGenerateNewMenuLevel", "@NewMenuLevel", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return newMenuLevel;
        }

        /// <summary>
        /// 添加员工信息
        /// </summary>
        /// <param name="employeeEntity">员工实体</param>
        /// <param name="dtEmployee">员工数据表</param>
        /// <returns></returns>
        public static string AddEmployees(EmployeesEntity employeeEntity, out DataTable dtEmployee)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@UserNo",SqlDbType.NVarChar,50),
                new SqlParameter("@NameCn",SqlDbType.NVarChar,50),
                new SqlParameter("@NameEn",SqlDbType.NVarChar,50),
                new SqlParameter("@Password",SqlDbType.NVarChar,200),
                new SqlParameter("@Sex",SqlDbType.VarChar,2),
                new SqlParameter("@DepartmentNo",SqlDbType.NVarChar,50),
                new SqlParameter("@Telephone",SqlDbType.NVarChar,50),
                new SqlParameter("@Address",SqlDbType.NVarChar,500),
                new SqlParameter("@OldUserNo",SqlDbType.NVarChar,150),
                new SqlParameter("@Access",SqlDbType.NVarChar,4000),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = employeeEntity.UserNo;
                sqlParameters[1].Value = employeeEntity.NameCn;
                sqlParameters[2].Value = employeeEntity.NameEn;
                sqlParameters[3].Value = employeeEntity.Password;
                sqlParameters[4].Value = employeeEntity.Sex;
                sqlParameters[5].Value = employeeEntity.DepartmentNo;
                sqlParameters[6].Value = employeeEntity.Telephone;
                sqlParameters[7].Value = employeeEntity.Address;
                sqlParameters[8].Value = employeeEntity.OldUserNo;
                sqlParameters[9].Value = employeeEntity.Access;
                sqlParameters[10].Direction = ParameterDirection.Output;
                sqlParameters[11].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddEmployee", sqlParameters, out dtEmployee);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 释放工单并生成序列号
        /// </summary>
        /// <param name="WOEntity">工单实体信息</param>
        /// <returns></returns>
        public static Task<string> ReleaseWO(WOEntity WOEntity)
        {
            Task<string> task = null;
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                task = Task.Run<string>(() =>
                {
                    sqlParameters = new SqlParameter[]
                    {
                     new SqlParameter("@WO",SqlDbType.NVarChar,400),
                     new SqlParameter("@WODescription",SqlDbType.NVarChar,500),
                     new SqlParameter("@WOCount",SqlDbType.Int),
                     new SqlParameter("@PN",SqlDbType.NVarChar,500),
                     new SqlParameter("@Flow",SqlDbType.NVarChar,200),
                     new SqlParameter("@OwnerManufacturer",SqlDbType.NVarChar,50),
                     new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                     new SqlParameter("@CustomStartSn",SqlDbType.NVarChar,200),
                     new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                     new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                    };
                    sqlParameters[0].Value = WOEntity.WO;
                    sqlParameters[1].Value = WOEntity.WODescription;
                    sqlParameters[2].Value = WOEntity.Count;
                    sqlParameters[3].Value = WOEntity.PN;
                    sqlParameters[4].Value = WOEntity.Flow;
                    sqlParameters[5].Value = WOEntity.OwnerManufacturer;
                    sqlParameters[6].Value = WOEntity.Actor;
                    sqlParameters[7].Value = WOEntity.CustomStartSn;
                    sqlParameters[8].Direction = ParameterDirection.Output;
                    sqlParameters[9].Direction = ParameterDirection.Output;
                    retMsg = sqlHelper.ExecuteStoredProcedure("procReleaseWoAndSnNew", sqlParameters);
                    return retMsg;
                });
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return task;
        }

        /// <summary>
        /// 管理员工菜单权限
        /// </summary>
        /// <param name="menuEntity"></param>
        public static bool ManageEmployeeMenuAccess(EmployeesEntity employeesEntity)
        {
            StringBuilder sql = new StringBuilder();
            bool result = false;
            try
            {
                sql.AppendFormat("update [dbo].[UserInfo] set Access='{0}' where UserNo='{1}'", employeesEntity.Access, employeesEntity.UserNo);
                result = sqlHelper.ExecuteNonQuery(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 添加流程信息
        /// </summary>
        /// <param name="routingEntity">流程实体</param>
        /// <param name="dtRoutings">返回流程数据集</param>
        /// <returns></returns>
        public static string AddRoutings(RoutingEntity routingEntity, out DataTable[] dtRoutings)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@PN",SqlDbType.NVarChar,200),
                new SqlParameter("@Flow",SqlDbType.NVarChar,200),
                new SqlParameter("@ProductionStage",SqlDbType.NVarChar,100),
                new SqlParameter("@StrStations",SqlDbType.NVarChar){Size=-1}, //对应数据库中的MAX
                new SqlParameter("@SplitChar",SqlDbType.VarChar,2),
                new SqlParameter("@SubFlow",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = routingEntity.PN;
                sqlParameters[1].Value = routingEntity.Flow;
                sqlParameters[2].Value = routingEntity.ProductionStage;
                sqlParameters[3].Value = routingEntity.Station;
                sqlParameters[4].Value = "|";
                sqlParameters[5].Value = routingEntity.SubFlow;
                sqlParameters[6].Value = routingEntity.Actor_M;
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatables("procAddRouting", sqlParameters, out dtRoutings, 5);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 菜单定义
        /// </summary>
        /// <param name="menuEntity">菜单实体</param>
        /// <returns></returns>
        public static bool MenuDefine(MenuNamedEntity menuEntity)
        {
            int affectLines = 0;//返回受影响的行数
            bool result = false;//返回的结果
            StringBuilder sql = new StringBuilder();//插入语句
            try
            {
                sql.AppendFormat("select count(1) from menudefine where MenuCn='{0}' or MenuEn='{1}'", menuEntity.MenuCn, menuEntity.MenuEn);
                affectLines = sqlHelper.ExecuteScalar<int>(sql.ToString());
                if (affectLines > 0)
                {
                    result = false;
                }
                else
                {
                    sql.Length = 0;
                    sql.AppendFormat("insert into MenuDefine(MenuEn,MenuCn,Remarks)values('{0}','{1}','{2}')", menuEntity.MenuEn, menuEntity.MenuCn, menuEntity.Remarks);
                    result = sqlHelper.ExecuteNonQuery(sql.ToString());
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 获取菜单定义信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetMenuDefineTable()
        {
            DataTable dt = new DataTable();
            StringBuilder sql = new StringBuilder();//插入语句
            try
            {
                sql.AppendFormat("select * from MenuDefine");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取所有员工信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetAllEmployeeInfo()
        {
            DataTable dt = new DataTable();
            StringBuilder sql = new StringBuilder();//插入语句
            try
            {
                sql.AppendFormat("select * from UserInfo");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 更新员工信息
        /// </summary>
        /// <param name="employees">员工实体类</param>
        /// <returns></returns>
        public static string UpdateEmployeeInfo(EmployeesEntity employees)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@UserNo",SqlDbType.NVarChar,50),
                new SqlParameter("@NameCn",SqlDbType.NVarChar,50),
                new SqlParameter("@NameEn",SqlDbType.NVarChar,50),
                new SqlParameter("@Password",SqlDbType.NVarChar,200),
                new SqlParameter("@Sex",SqlDbType.Char,2),
                new SqlParameter("@DepartmentNo",SqlDbType.NVarChar,50),
                new SqlParameter("@Telephone",SqlDbType.NVarChar,50),
                new SqlParameter("@Address",SqlDbType.NVarChar,500),
                new SqlParameter("@OldUserNo",SqlDbType.NVarChar,150),
                new SqlParameter("@Access",SqlDbType.NVarChar,4000),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000),
                };
                sqlParameters[0].Value = employees.UserNo ?? "";
                sqlParameters[1].Value = employees.NameCn ?? "";
                sqlParameters[2].Value = employees.NameEn ?? "";
                sqlParameters[3].Value = employees.Password ?? "";
                sqlParameters[4].Value = employees.Sex ?? "";
                sqlParameters[5].Value = employees.DepartmentNo ?? "";
                sqlParameters[6].Value = employees.Telephone ?? "";
                sqlParameters[7].Value = employees.Address ?? "";
                sqlParameters[8].Value = employees.OldUserNo ?? "";
                sqlParameters[9].Value = employees.Access ?? "";
                sqlParameters[10].Direction = ParameterDirection.Output;
                sqlParameters[11].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procUpdateEmployee", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 删除员工信息
        /// </summary>
        /// <param name="employees">员工实体类</param>
        /// <returns></returns>
        public static bool DeleteEmployeeInfo(EmployeesEntity employees)
        {
            StringBuilder sql = new StringBuilder();
            try
            {
                sql.AppendFormat("delete from UserInfo where UserNo='{0}'", employees.UserNo);
                return sqlHelper.ExecuteNonQuery(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 验证员工是否有相关模块权限
        /// </summary>
        /// <param name="authorityCode">权限代码</param>
        /// <returns></returns>
        public static string EmployeeIsHaveModuleAuthority(string authorityCode)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@UserNo",SqlDbType.NVarChar,50),
                new SqlParameter("@AuthorityCode",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000),
                };
                sqlParameters[0].Value = LogInInfo.User;
                sqlParameters[1].Value = authorityCode;
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procIsHaveModuleAuthority", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 获取配置的菜单项
        /// </summary>
        /// <returns></returns>
        public static DataTable GetConfigMenuTable()
        {
            StringBuilder sql = new StringBuilder();//查询语句
            DataTable dtSource = new DataTable();
            try
            {
                sql.AppendFormat("select C.MenuItemId,M.MenuEn,M.MenuCn,M.Remarks from MenuDefine M left join ClientMenuConfig C on M.Id=C.MDId where C.MDId is not null");
                dtSource = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtSource;
        }

        /// <summary>
        /// 获取没有配置的菜单项
        /// </summary>
        /// <returns></returns>
        public static DataTable GetNoConfigMenuTable()
        {
            StringBuilder sql = new StringBuilder();//查询语句
            DataTable dtSource = new DataTable();
            try
            {
                sql.AppendFormat("select M.Id,M.MenuEn,M.MenuCn from MenuDefine M left join ClientMenuConfig C on M.Id=C.MDId where C.MDId is null order by M.Id");
                dtSource = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtSource;
        }

        /// <summary>
        /// 配置客户端菜单
        /// </summary>
        /// <param name="menuEntity">菜单实体</param>
        /// <param name="dtMenu">菜单数据表</param>
        /// <returns></returns>
        public static string ConfigClientMenu(MenuEntity menuEntity, out DataTable dtMenu)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Header",SqlDbType.NVarChar,50),
                new SqlParameter("@OwnerId",SqlDbType.Int),
                new SqlParameter("@MenuItemLevel",SqlDbType.Int),
                new SqlParameter("@ActorLevel",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = menuEntity.MenuEn;
                sqlParameters[1].Value = menuEntity.OwnerId;
                sqlParameters[2].Value = menuEntity.MenuLevel;
                sqlParameters[3].Value = menuEntity.MenuAccess;
                sqlParameters[4].Direction = ParameterDirection.Output;
                sqlParameters[5].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procConfigClientMenu", sqlParameters, out dtMenu);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 生成序列号格式
        /// </summary>
        /// <param name="pnType">机种类型</param>
        /// <returns></returns>
        public static string GenerateSnFormat(string pnType = "")
        {
            string snFormat = string.Empty;
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                     {
                        new SqlParameter("@PnType",SqlDbType.NVarChar,50),
                        new SqlParameter("@GenerateSnFormat",SqlDbType.NVarChar,200)
                     };
                sqlParameters[0].Value = pnType;
                sqlParameters[1].Direction = ParameterDirection.Output;
                snFormat = sqlHelper.ExecuteStoredProcedure("procGenerateSnFormatNew", "@GenerateSnFormat", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return snFormat;
        }

        /// <summary>
        /// 添加机种信息
        /// </summary>
        /// <param name="partNumberEntity">机种信息实体</param>
        /// <param name="snFormatEntity">序列号格式实体</param>
        /// <param name="dtPartNumber">机种信息数据表</param>
        /// <returns></returns>
        public static string AddPartNumber(PartNumberEntity partNumberEntity, SnFormatEntity snFormatEntity, out DataTable dtPartNumber)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                //机种基础参数
                new SqlParameter("@PartNumber",SqlDbType.NVarChar,500),
                new SqlParameter("@SnFormat",SqlDbType.NVarChar,200),
                new SqlParameter("@UnitCode",SqlDbType.NVarChar,200),
                new SqlParameter("@KitCount",SqlDbType.Int),
                new SqlParameter("@PrintCopiesNum",SqlDbType.Int),
                new SqlParameter("@PnType",SqlDbType.NVarChar,50),
                new SqlParameter("@LPCId",SqlDbType.Int),
                new SqlParameter("@PPCId",SqlDbType.Int),
                new SqlParameter("@PerBoxNum",SqlDbType.Int),
                //序列号格式参数
                new SqlParameter("@CustomerCode",SqlDbType.NVarChar,50),
                new SqlParameter("@YearSection",SqlDbType.NVarChar,50),
                new SqlParameter("@MonthSection",SqlDbType.NVarChar,50),
                new SqlParameter("@WeekSection",SqlDbType.NVarChar,50),
                new SqlParameter("@WeekDaySection",SqlDbType.NVarChar,50),
                new SqlParameter("@DaySection",SqlDbType.NVarChar,50),
                new SqlParameter("@PNCode",SqlDbType.NVarChar,50),
                new SqlParameter("@SerialNumber",SqlDbType.NVarChar,50),
                new SqlParameter("@SerialNumberDigit",SqlDbType.Int),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@ComponentSequence",SqlDbType.NVarChar,200),
                new SqlParameter("@CustomerCodeStartIndex",SqlDbType.Int),
                new SqlParameter("@CustomerCodeStopIndex",SqlDbType.Int),
                new SqlParameter("@YearSectionStartIndex",SqlDbType.Int),
                new SqlParameter("@YearSectionStopIndex",SqlDbType.Int),
                new SqlParameter("@MonthSectionStartIndex",SqlDbType.Int),
                new SqlParameter("@MonthSectionStopIndex",SqlDbType.Int),
                new SqlParameter("@WeekSectionStartIndex",SqlDbType.Int),
                new SqlParameter("@WeekSectionStopIndex",SqlDbType.Int),
                new SqlParameter("@WeekDaySectionStartIndex",SqlDbType.Int),
                new SqlParameter("@WeekDaySectionStopIndex",SqlDbType.Int),
                new SqlParameter("@DaySectionStartIndex",SqlDbType.Int),
                new SqlParameter("@DaySectionStopIndex",SqlDbType.Int),
                new SqlParameter("@PNCodeStartIndex",SqlDbType.Int),
                new SqlParameter("@PNCodeStopIndex",SqlDbType.Int),
                new SqlParameter("@SerialNumberStartIndex",SqlDbType.Int),
                new SqlParameter("@SerialNumberStopIndex",SqlDbType.Int),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                //机种基础参数值
                sqlParameters[0].Value = partNumberEntity.PN;
                sqlParameters[1].Value = partNumberEntity.SnFormat;
                sqlParameters[2].Value = partNumberEntity.UnitCode;
                sqlParameters[3].Value = partNumberEntity.KitCount;
                sqlParameters[4].Value = partNumberEntity.PrintCopiesNum;
                sqlParameters[5].Value = partNumberEntity.PnType;
                sqlParameters[6].Value = partNumberEntity.LPCId.Id;
                sqlParameters[7].Value = partNumberEntity.PPCId.Id;
                sqlParameters[8].Value = partNumberEntity.PerBoxNum;
                //序列号格式参数值
                sqlParameters[9].Value = snFormatEntity.CustomerCode ?? "";
                sqlParameters[10].Value = snFormatEntity.YearSection ?? "";
                sqlParameters[11].Value = snFormatEntity.MonthSection ?? "";
                sqlParameters[12].Value = snFormatEntity.WeekSection ?? "";
                sqlParameters[13].Value = snFormatEntity.WeekDaySection ?? "";
                sqlParameters[14].Value = snFormatEntity.DaySection ?? "";
                sqlParameters[15].Value = snFormatEntity.PNCode ?? "";
                sqlParameters[16].Value = snFormatEntity.SerialNumber ?? "";
                sqlParameters[17].Value = snFormatEntity.SerialNumberDigit;
                sqlParameters[18].Value = snFormatEntity.Actor ?? "";
                sqlParameters[19].Value = snFormatEntity.ComponentSequence ?? "";
                sqlParameters[20].Value = snFormatEntity.CustomerCodeStartIndex;
                sqlParameters[21].Value = snFormatEntity.CustomerCodeStopIndex;
                sqlParameters[22].Value = snFormatEntity.YearSectionStartIndex;
                sqlParameters[23].Value = snFormatEntity.YearSectionStopIndex;
                sqlParameters[24].Value = snFormatEntity.MonthSectionStartIndex;
                sqlParameters[25].Value = snFormatEntity.MonthSectionStopIndex;
                sqlParameters[26].Value = snFormatEntity.WeekSectionStartIndex;
                sqlParameters[27].Value = snFormatEntity.WeekSectionStopIndex;
                sqlParameters[28].Value = snFormatEntity.WeekDaySectionStartIndex;
                sqlParameters[29].Value = snFormatEntity.WeekDaySectionStopIndex;
                sqlParameters[30].Value = snFormatEntity.DaySectionStartIndex;
                sqlParameters[31].Value = snFormatEntity.DaySectionStopIndex;
                sqlParameters[32].Value = snFormatEntity.PNCodeStartIndex;
                sqlParameters[33].Value = snFormatEntity.PNCodeStopIndex;
                sqlParameters[34].Value = snFormatEntity.SerialNumberStartIndex;
                sqlParameters[35].Value = snFormatEntity.SerialNumberStopIndex;

                sqlParameters[36].Direction = ParameterDirection.Output;
                sqlParameters[37].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddPartNumber", sqlParameters, out dtPartNumber);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询机种信息
        /// </summary>
        /// <param name="partNumberEntity">机种信息实体</param>
        /// <param name="dtPartNumber">机种信息数据表</param>
        /// <returns></returns>
        public static string QueryPartNumber(PartNumberEntity partNumberEntity, out DataTable dtPartNumber)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@PnType",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000),
                };
                sqlParameters[0].Value = partNumberEntity.PN;
                sqlParameters[1].Value = partNumberEntity.PnType;
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryPN", sqlParameters, out dtPartNumber);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 返回系统中机种信息
        /// </summary>
        /// <param name="partnumType">机种类型</param>
        /// <returns></returns>
        public static DataTable GetPNs(EnumPNType partnumType)
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                switch (partnumType)
                {
                    case EnumPNType.Ant:
                        sql.AppendFormat("select * from PN where PnType='{0}' order by PartNumber", "天线");
                        break;

                    case EnumPNType.Filter:
                        sql.AppendFormat("select * from PN where PnType='{0}' order by PartNumber", "滤波器");
                        break;

                    case EnumPNType.Ret:
                        sql.AppendFormat("select * from PN where PnType='{0}' order by PartNumber", "马达");
                        break;

                    case EnumPNType.All:
                        sql.AppendFormat("select * from PN order by PartNumber");
                        break;

                    default:
                        sql.AppendFormat("select * from PN order by PartNumber");
                        break;
                }
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }
        /// <summary>
        /// 获取标签模版
        /// </summary>
        /// <returns></returns>
        public static DataTable GetLabelTemplate()
        {
            StringBuilder sql = new StringBuilder();
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from Template");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }
        /// <summary>
        /// 获取标签模版变量
        /// </summary>
        /// <returns></returns>
        public static DataTable GetLabelTemplateVariable()
        {
            StringBuilder sql = new StringBuilder();
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from TemplateVariable");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }
        /// <summary>
        /// 通过序列号获得机种信息
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <returns></returns>
        public static string GetPNBySn(string sn)
        {
            StringBuilder sql = new StringBuilder();
            string pn = string.Empty;//机种信息
            try
            {
                sql.AppendFormat("select PN from vw_SN with(nolock) where Sn='{0}'", sn);
                pn = sqlHelper.ExecuteScalar<string>(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return pn;
        }

        /// <summary>
        /// 添加捆绑站位信息
        /// </summary>
        /// <param name="flow">流程</param>
        /// <param name="strStations">站位字符串《Station1|Station2|Station3》</param>
        /// <returns></returns>
        public static string AddBindingStation(string flow, string strStations)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Flow",SqlDbType.NVarChar,50),
                new SqlParameter("@StrStation",SqlDbType.NVarChar){Size=-1},
                new SqlParameter("@StateCode",SqlDbType.NVarChar,2),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000),
                };
                sqlParameters[0].Value = flow ?? "";
                sqlParameters[1].Value = strStations ?? "";
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procAddBindingStation", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询绑定的站位信息
        /// </summary>
        /// <param name="flow">流程</param>
        /// <param name="dtBindingStations">绑定站位基础信息表</param>
        /// <param name="isContainsDelete">是否包含删除的记录</param>
        /// <returns></returns>
        public static string SearchBindingStation(string flow, out DataTable dtBindingStations, bool isContainsDelete = false)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Flow",SqlDbType.NVarChar,50),
                new SqlParameter("@IsContainsDelete",SqlDbType.NVarChar,2),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,2),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000),
                };
                sqlParameters[0].Value = flow ?? "";
                sqlParameters[1].Value = isContainsDelete == true ? "Y" : "N";
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryBindingStation", sqlParameters, out dtBindingStations);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 删除绑定的站位
        /// </summary>
        /// <param name="id">Id</param>
        /// <returns></returns>
        public static string DeleteBindingStation(int id)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Id",SqlDbType.Int),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,2),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000),
                };
                sqlParameters[0].Value = id;
                sqlParameters[1].Direction = ParameterDirection.Output;
                sqlParameters[2].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procDeleteBindingStation", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 通过机种获得流程
        /// </summary>
        /// <param name="partNumber">机种</param>
        /// <returns></returns>
        public static DataTable GetFlowsByPN(string partNumber)
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from Routing_M where PN='{0}'", partNumber);
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 通过机种获得工单
        /// </summary>
        /// <param name="partNumber">机种</param>
        /// <returns></returns>
        public static DataTable GetWOsByPN(string partNumber)
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from WO where PN='{0}' order by WO", partNumber);
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 通过机种获得站位《包括PP/MP/OBA..》
        /// </summary>
        /// <param name="partNumber">机种</param>
        /// <returns></returns>
        public static DataTable GetStationsByPN(string partNumber)
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select Station from vw_Routing where PN='{0}' group by Station", partNumber);
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获得机种的信息
        /// </summary>
        /// <param name="partNumber">机种名称</param>
        /// <returns></returns>
        public static DataTable GetPNInfo(string partNumber)
        {
            StringBuilder sql = new StringBuilder();
            DataTable dtPN = new DataTable();
            try
            {
                sql.AppendFormat("select * from PN  where PartNumber='{0}'", partNumber);
                dtPN = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtPN;
        }

        /// <summary>
        /// 获取工单信息
        /// </summary>
        /// <param name="WO">工单(*代表全局搜索)</param>
        /// <returns></returns>
        public static DataTable GetWOInfo(string WO)
        {
            DataTable dt = new DataTable();
            StringBuilder sql = new StringBuilder();
            try
            {
                //表示搜索全部工单信息
                if (WO == "*")
                {
                    sql.AppendFormat("select * from WO order by CreateAt");
                }
                else
                {
                    sql.AppendFormat("select * from WO where WO='{0}'", WO);
                }
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 通过机种获取工单信息
        /// </summary>
        /// <param name="pn">机种(*代表全局搜索)</param>
        /// <returns></returns>
        public static DataTable GetWOInfoByPn(string pn)
        {
            DataTable dt = new DataTable();
            StringBuilder sql = new StringBuilder();
            try
            {
                //表示搜索全部工单信息
                if (pn == "*")
                {
                    sql.AppendFormat("select * from WO order by CreateAt");
                }
                else
                {
                    sql.AppendFormat("select * from WO where PN='{0}' order by CreateAt desc", pn);
                }
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取员工信息
        /// </summary>
        /// <param name="UserNo">工号(*代表全局搜索)</param>
        /// <returns></returns>
        public static DataTable GetUserInfo(string UserNo)
        {
            DataTable dt = new DataTable();
            StringBuilder sql = new StringBuilder();
            try
            {
                //表示搜索全部工单信息
                if (UserNo == "*")
                {
                    sql.AppendFormat("select * from [dbo].[UserInfo] order by UserNo");
                }
                else
                {
                    sql.AppendFormat("select * from [dbo].[UserInfo] where UserNo='{0}'", UserNo);
                }
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取产品阶段信息
        /// </summary>
        /// <returns></returns>
        public static DataTable GetProductionStages()
        {
            StringBuilder sql = new StringBuilder();//数据库查询语句
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select * from ProductionStage");
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取流程通过生产阶段
        /// </summary>
        /// <param name="Flow">生产阶段</param>
        /// <param name="dtFlow">流程表</param>
        /// <returns></returns>
        public static string GetRoutingByFlow(string Flow, out DataTable dtFlow)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@Flow",SqlDbType.NVarChar,200),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = Flow;
                sqlParameters[1].Direction = ParameterDirection.Output;
                sqlParameters[2].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryRouting", sqlParameters, out dtFlow);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 统计工位的产出数量
        /// </summary>
        /// <param name="dtOutput">产出数据表</param>
        /// <param name="pn">机种</param>
        /// <param name="station">工位</param>
        /// <param name="startTime">开始时间</param>
        /// <param name="stopTime">结束时间</param>
        /// <param name="sequence">测试次数 *代表最后一次</param>
        /// <returns></returns>
        public static string StatisticsStationOutput(out DataTable dtOutput, string pn = "", string station = "", string startTime = "", string stopTime = "", string sequence = "*")
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@Station",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000),
                };
                sqlParameters[0].Value = pn;
                sqlParameters[1].Value = station;
                sqlParameters[2].Value = startTime;
                sqlParameters[3].Value = stopTime;
                sqlParameters[4].Value = sequence;
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procStatisticsStationOutput", sqlParameters, out dtOutput);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 通过机种获得流程
        /// </summary>
        /// <param name="PN">机种</param>
        /// <param name="dts">流程数据表集</param>
        /// <returns></returns>
        public static string GetRoutingByPN(string PN, out DataTable[] dts)
        {
            string retMsg = string.Empty;//返回的结果信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[]
                {
                new SqlParameter("@PN",SqlDbType.NVarChar,200),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,300),
                };
                sqlParameters[0].Value = PN;
                sqlParameters[1].Direction = ParameterDirection.Output;
                sqlParameters[2].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatables("procQueryRouting", sqlParameters, out dts, 2);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }
        /// <summary>
        /// 添加每个机种流程每个站位在包装、入库、出货的检测标准
        /// </summary>
        /// <param name="finalCheckStation">哪个站位做检查</param>
        /// <param name="standard">标准</param>
        /// <param name="routing">需要修改的流程实体</param>
        public static void AddStationCheckStandard(string finalCheckStation, string standard, RoutingEntity routing)
        {
            try
            {
                var sql = new StringBuilder();
                switch (finalCheckStation.ToUpper())
                {
                    case "PACKING":
                        sql.AppendFormat("update Routing_C set PackingCheckStandard='{0}' where MId={1} and Sequence={2}", standard=="NA"?"NULL":standard, routing.MId, routing.Sequence);
                        break;
                    case "END":
                        sql.AppendFormat("update Routing_C set EndCheckStandard='{0}' where MId={1} and Sequence={2}", standard, routing.MId, routing.Sequence);
                        break;
                    case "SHIP":
                        sql.AppendFormat("update Routing_C set ShipCheckStandard='{0}' where MId={1} and Sequence={2}", standard, routing.MId, routing.Sequence);
                        break;
                    default:
                        break;
                }
                if (sql.ToString() != "")
                {
                    sqlHelper.ExecuteNonQuery(sql.ToString());
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
          
        }
        /// <summary>
        /// 验证END工站输入的信息
        /// </summary>
        /// <param name="SN">序列号</param>
        /// <returns></returns>
        public static string VerifyEndWorkStation(string SN)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,2),
                  new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = SN;
                sqlParameters[1].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[2].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedure("procVerifyEndWorkStation", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加END工序Log信息
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dtTracking">序列号Log数据表</param>
        /// <returns></returns>
        public static string AddEndTracking(TrackingEntity tEntity, out DataTable dtTracking)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@Result",SqlDbType.NVarChar,4),
                new SqlParameter("@EquipmentName",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.DateTime),
                new SqlParameter("@StopTime",SqlDbType.DateTime),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@TunningSource",SqlDbType.NVarChar,50),
                new SqlParameter("@TunningStation",SqlDbType.NVarChar,50),
                new SqlParameter("@Defective",SqlDbType.NVarChar,200),
                new SqlParameter("@IMDSource",SqlDbType.NVarChar,50),
                new SqlParameter("@IMDTestValue",SqlDbType.NVarChar,50),
                new SqlParameter("@IMDSpecUpperLimit",SqlDbType.NVarChar,50),
                new SqlParameter("@IMDSpecLowerLimit",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.Sn;
                sqlParameters[1].Value = tEntity.Station;
                sqlParameters[2].Value = tEntity.Result;
                sqlParameters[3].Value = tEntity.EquipmentName;
                sqlParameters[4].Value = tEntity.StartTime;
                sqlParameters[5].Value = tEntity.StopTime;
                sqlParameters[6].Value = tEntity.Actor;
                sqlParameters[7].Value = tEntity.TunningInfo?.Source ?? "";
                sqlParameters[8].Value = tEntity.TunningInfo?.Station ?? "";
                sqlParameters[9].Value = tEntity.TunningInfo?.Defective ?? "";
                sqlParameters[10].Value = tEntity.IMDInfo?.Source ?? "";
                sqlParameters[11].Value = tEntity.IMDInfo?.TestValue ?? "";
                sqlParameters[12].Value = tEntity.IMDInfo?.UpperLimit ?? "";
                sqlParameters[13].Value = tEntity.IMDInfo?.LowerLimit ?? "";
                sqlParameters[14].Direction = ParameterDirection.Output;
                sqlParameters[15].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddTracking", sqlParameters, out dtTracking);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加生产计划产量
        /// </summary>
        /// <param name="tEntity">生产计划实体类</param>
        /// <returns></returns>
        public static string AddProductionPlanOutput(ProductionPlanEntity tEntity)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@WO",SqlDbType.NVarChar,400),
                new SqlParameter("@Shift",SqlDbType.NVarChar,10),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@PlanOutput",SqlDbType.Int),
                new SqlParameter("@WeekDay",SqlDbType.Char,1),
                new SqlParameter("@Week",SqlDbType.Char,2),
                new SqlParameter("@Year",SqlDbType.VarChar,40),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.WO;
                sqlParameters[1].Value = tEntity.Shift;
                sqlParameters[2].Value = tEntity.Station;
                sqlParameters[3].Value = tEntity.PlanOutput;
                sqlParameters[4].Value = tEntity.WeekDay;
                sqlParameters[5].Value = tEntity.Week;
                sqlParameters[6].Value = tEntity.Year;
                sqlParameters[7].Value = tEntity.Actor;
                sqlParameters[8].Direction = ParameterDirection.Output;
                sqlParameters[9].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procAddProductionPlan", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加包装工序Log信息
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dtTracking">序列号Log数据表</param>
        /// <returns></returns>
        public static string AddPackingTracking(TrackingEntity tEntity, List<DataTable> dts)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@Result",SqlDbType.NVarChar,4),
                new SqlParameter("@EquipmentName",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.DateTime),
                new SqlParameter("@StopTime",SqlDbType.DateTime),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.Sn;
                sqlParameters[1].Value = tEntity.Station;
                sqlParameters[2].Value = tEntity.Result;
                sqlParameters[3].Value = tEntity.EquipmentName;
                sqlParameters[4].Value = tEntity.StartTime;
                sqlParameters[5].Value = tEntity.StopTime;
                sqlParameters[6].Value = tEntity.Actor;
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatables("procAddTracking", sqlParameters, dts);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加批量包装工序Log信息《针对一箱多包的情况》
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dtTracking">序列号Log数据表</param>
        /// <returns></returns>
        public static string AddBatchPackingTracking(TrackingEntity tEntity, out DataTable dtLastStatus)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@StrSns",SqlDbType.VarChar),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@Result",SqlDbType.NVarChar,4),
                new SqlParameter("@EquipmentName",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.DateTime),
                new SqlParameter("@StopTime",SqlDbType.DateTime),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.Sn;
                sqlParameters[1].Value = tEntity.Station;
                sqlParameters[2].Value = tEntity.Result;
                sqlParameters[3].Value = tEntity.EquipmentName;
                sqlParameters[4].Value = tEntity.StartTime;
                sqlParameters[5].Value = tEntity.StopTime;
                sqlParameters[6].Value = tEntity.Actor;
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddBatchTracking", sqlParameters, out dtLastStatus);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 验证包装工站输入的信息
        /// </summary>
        /// <param name="SN">序列号</param>
        /// <returns></returns>
        public static string VerifyPackingWorkStation(string SN, List<DataTable> dataTables)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,2),
                  new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = SN;
                sqlParameters[1].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[2].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatables("procVerifyPackingWorkStation", sqlParameters, dataTables);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加标签打印Log记录
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <returns></returns>
        public static string AddLabelPrintTracking(TrackingEntity tEntity)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@Result",SqlDbType.NVarChar,4),
                new SqlParameter("@EquipmentName",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.DateTime),
                new SqlParameter("@StopTime",SqlDbType.DateTime),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.Sn;
                sqlParameters[1].Value = tEntity.Station;
                sqlParameters[2].Value = tEntity.Result;
                sqlParameters[3].Value = tEntity.EquipmentName;
                sqlParameters[4].Value = tEntity.StartTime;
                sqlParameters[5].Value = tEntity.StopTime;
                sqlParameters[6].Value = tEntity.Actor;
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procAddTracking", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 添加标签打印Log记录
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <returns></returns>
        public static string AddBatchLabelPrintTracking(TrackingEntity tEntity, out DataTable dtLastStatus)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@StrSns",SqlDbType.VarChar),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@Result",SqlDbType.NVarChar,4),
                new SqlParameter("@EquipmentName",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.DateTime),
                new SqlParameter("@StopTime",SqlDbType.DateTime),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.Sn;
                sqlParameters[1].Value = tEntity.Station;
                sqlParameters[2].Value = tEntity.Result;
                sqlParameters[3].Value = tEntity.EquipmentName;
                sqlParameters[4].Value = tEntity.StartTime;
                sqlParameters[5].Value = tEntity.StopTime;
                sqlParameters[6].Value = tEntity.Actor;
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procAddBatchTracking", sqlParameters, out dtLastStatus);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 输入的工单是否OK
        /// </summary>
        /// <param name="WO">工单</param>
        /// <param name="retMsg">返回信息</param>
        /// <returns></returns>
        public static bool WOIsOk(string WO, out string retMsg)
        {
            string pattern = string.Empty;
            try
            {
                pattern = @"^(wo|WO|Wo|wO)\w+$";
                Regex regex = new Regex(pattern);
                if (regex.IsMatch(WO))
                {
                    if (!WOIsExists(WO))
                    {
                        retMsg = "OK";
                        return true;
                    }
                    else
                    {
                        retMsg = "工单【" + WO + "】在系统中已经存在,请不要重复添加.";
                        return false;
                    }
                }
                else
                {
                    retMsg = "工单【" + WO + "】格式不正确，要以[WO|wO|wo|Wo]开头.";
                    return false;
                }
            }
            catch (Exception ex)
            {
                retMsg = ex.Message;
                LogHelper.WriteLog(ex.Message, ex);
                return false;
            }
        }

        /// <summary>
        /// 查询工单再系统中是否存在
        /// </summary>
        /// <param name="WO"></param>
        /// <returns></returns>
        public static bool WOIsExists(string WO)
        {
            StringBuilder sql = new StringBuilder();
            bool result = false;
            try
            {
                sql.AppendFormat("select count(1) from WO where WO='{0}'", WO);
                result = sqlHelper.ExecuteScalar<int>(sql.ToString()) > 0 ? true : false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 查询序列号信息在系统中是否存在
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <returns></returns>
        public static bool SNIsExists(string sn)
        {
            StringBuilder sql = new StringBuilder();
            bool result = false;
            try
            {
                sql.AppendFormat("select count(1) from vw_SN with(nolock) where Sn='{0}'", sn);
                result = sqlHelper.ExecuteScalar<int>(sql.ToString()) > 0 ? true : false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return result;
        }

        

        /// <summary>
        /// 查询序列号对应的机种信息
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <returns></returns>
        public static string SnOwnerPN(string sn)
        {
            string pn = string.Empty;//机种
            StringBuilder sql = new StringBuilder();//sql语句
            try
            {
                sql.AppendFormat("select PN from vw_SN with(nolock) where Sn='{0}'", sn);
                pn = sqlHelper.ExecuteScalar<string>(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception("Error Source:【" + nameof(SnOwnerPN) + "】,Error Msg:【" + ex.Message + "】");
            }
            return pn;
        }

        /// <summary>
        /// 通过工单获取标签打印信息《已经打印和未打印》
        /// </summary>
        /// <param name="WO">工单</param>
        /// <returns></returns>
        public static DataTable GetLabelPrintInfoByWO(string WO)
        {
            StringBuilder sql = new StringBuilder();
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select *,case when  PretestStation='LPRINT' and CompletedStation='LPRINT' then 'N' else 'Y' end as 'IsPrinted' from vw_SN with(nolock) where WO='{0}' order by sn", WO);
                dt = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dt;
        }

        /// <summary>
        /// 获取标签打印配置参数《包括打印的行数打印模板的变量模板的名称等》
        /// </summary>
        /// <param name="PN">机种</param>
        /// <returns></returns>
        //public static DataTable GetLabelPrintConfigInfoByPN(string PN)
        //{
        //    StringBuilder sql = new StringBuilder();
        //    DataTable dt = new DataTable();
        //    try
        //    {
        //        sql.AppendFormat("select * from PN p inner join LabelPrintConfig c on p.LPCId=c.Id where PartNumber='{0}'", PN);
        //        dt = sqlHelper.GetTable(sql.ToString());
        //    }
        //    catch (Exception ex)
        //    {
        //        LogHelper.WriteLog(ex.Message, ex);
        //        throw new Exception(ex.Message);
        //    }
        //    return dt;
        //}

        /// <summary>
        /// 是不是数字
        /// </summary>
        /// <param name="number">数字</param>
        /// <returns></returns>
        public static bool IsNumber(string number)
        {
            string pattern = "^[1-9][0-9]*$";
            Regex regex = new Regex(pattern);
            return regex.IsMatch(number);
        }

        /// <summary>
        /// 是否是有效指标
        /// </summary>
        /// <param name="content">指标</param>
        /// <returns></returns>
        public static bool IsValidSpec(string content)
        {
            if (content == "")
                return false;
            //return content == "" ? false : true;
            string pattern = @"^-?\d*(\.\d+)?$";
            Regex regex = new Regex(pattern);
            return regex.IsMatch(content);
        }

        /// <summary>
        /// 杀掉进程
        /// </summary>
        /// <param name="processName">进程名</param>
        public static void KillProcess(string processName)
        {
            foreach (Process p in Process.GetProcesses())
            {
                if (p.ProcessName.Contains(processName))
                {
                    try
                    {
                        p.Kill();
                        p.WaitForExit(); // possibly with a timeout
                    }
                    catch (Win32Exception e)
                    {
                        throw new Exception(e.Message);
                    }
                    catch (InvalidOperationException e)
                    {
                        throw new Exception(e.Message);
                    }
                }
            }
        }

        /// <summary>
        /// 查询工单信息《根据机种，工单，序列号》
        /// </summary>
        /// <param name="sEntity">序列号实体</param>
        /// <param name="dts">工单数据表</param>
        /// <returns></returns>
        public static string QueryWODetails(SNEntity sEntity, List<DataTable> dts)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,200),
                new SqlParameter("@WO",SqlDbType.NVarChar,400),
                new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = sEntity.PN;
                sqlParameters[1].Value = sEntity.WO;
                sqlParameters[2].Value = sEntity.SN;
                sqlParameters[3].Direction = ParameterDirection.Output;
                sqlParameters[4].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatables("procQueryWO", sqlParameters, dts);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询调试信息
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dt">调试信息数据表</param>
        /// <returns></returns>
        public static string QueryTunning(TrackingCombineSnEntity tEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.PN ?? "";
                sqlParameters[1].Value = tEntity.Actor ?? "";
                sqlParameters[2].Value = tEntity.StartTime ?? "";
                sqlParameters[3].Value = tEntity.StopTime ?? "";
                sqlParameters[4].Value = tEntity.TestSequence ?? "*";
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryTunning", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询生产计划和实际产量信息
        /// </summary>
        /// <param name="tEntity">实体</param>
        /// <param name="dt">产量信息数据表</param>
        /// <returns></returns>
        public static string QueryProductionPlanAndActualOutput(ProductionPlanAndActualEntity tEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@WO",SqlDbType.NVarChar,400),
                new SqlParameter("@PN",SqlDbType.NVarChar,500),
                new SqlParameter("@Station",SqlDbType.NVarChar,200),
                new SqlParameter("@WeekDay",SqlDbType.NVarChar,50),
                new SqlParameter("@Week",SqlDbType.Char,2),
                new SqlParameter("@Year",SqlDbType.VarChar,4),
                new SqlParameter("@Shift",SqlDbType.NVarChar,10),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.WO ?? "";
                sqlParameters[1].Value = tEntity.PN ?? "";
                sqlParameters[2].Value = tEntity.Station ?? "";
                sqlParameters[3].Value = tEntity.WeekDay ?? "";
                sqlParameters[4].Value = tEntity.Week ?? "*";
                sqlParameters[5].Value = tEntity.Year ?? "";
                sqlParameters[6].Value = tEntity.Shift ?? "*";
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryProductionPlanAndActualOutput", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询调试详细信息
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dt">调试信息数据表</param>
        /// <returns></returns>
        public static string QueryTunningDetails(TrackingCombineSnEntity tEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,1),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tEntity.PN ?? "";
                sqlParameters[1].Value = tEntity.Actor ?? "";
                sqlParameters[2].Value = tEntity.TestSequence ?? "*";
                sqlParameters[3].Value = tEntity.StartTime ?? "";
                sqlParameters[4].Value = tEntity.StopTime ?? "";
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryTunningDetails", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询互调详细信息《针对于报告生成站位》
        /// </summary>
        /// <param name="tEntity">Log实体</param>
        /// <param name="dt">互调信息数据表</param>
        /// <returns></returns>
        public static string QueryIMDDetails(TrackingEntity tEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@Sn",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000)
                };
                sqlParameters[0].Value = tEntity.Sn ?? "";
                sqlParameters[1].Value = tEntity.TestSequence ?? "2";
                sqlParameters[2].Direction = ParameterDirection.Output;
                sqlParameters[3].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryIMDDetails", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 统计站位产量
        /// </summary>
        /// <param name="tsEntity">实体类</param>
        /// <param name="dt">输出数据集</param>
        /// <returns></returns>
        public static string StatisticsStationOutputs(TrackingCombineSnEntity tsEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@Station",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tsEntity.PN ?? "";
                sqlParameters[1].Value = tsEntity.Station ?? "";
                sqlParameters[2].Value = tsEntity.StartTime ?? "";
                sqlParameters[3].Value = tsEntity.StopTime ?? "";
                sqlParameters[4].Value = tsEntity.TestSequence ?? "";
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procStatisticsStationOutput", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 统计站位产量详细信息
        /// </summary>
        /// <param name="tsEntity">实体类</param>
        /// <param name="dt">输出数据集</param>
        /// <returns></returns>
        public static string StatisticsStationOutputDetails(TrackingCombineSnEntity tsEntity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@Station",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = tsEntity.PN ?? "";
                sqlParameters[1].Value = tsEntity.Station ?? "";
                sqlParameters[2].Value = tsEntity.StartTime ?? "";
                sqlParameters[3].Value = tsEntity.StopTime ?? "";
                sqlParameters[4].Value = tsEntity.TestSequence ?? "";
                sqlParameters[5].Direction = ParameterDirection.Output;
                sqlParameters[6].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procStatisticsStationOutputDetails", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询IMD《互调》良率
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="dt">良率汇总数据</param>
        /// <returns></returns>
        public static string QueryIMDYields(TrackingCombineSnEntity entity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@WO",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@Source",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000)
                };
                sqlParameters[0].Value = entity.PN;
                sqlParameters[1].Value = entity.WO;
                sqlParameters[2].Value = entity.Actor ?? "";
                sqlParameters[3].Value = entity.IMDInfo.Source ?? "";
                sqlParameters[4].Value = entity.StartTime ?? "";
                sqlParameters[5].Value = entity.StopTime ?? "";
                sqlParameters[6].Value = entity.TestSequence ?? "";
                sqlParameters[7].Direction = ParameterDirection.Output;
                sqlParameters[8].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryIMDYield", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询IMD《互调》详细信息
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="dt">互调基础数据</param>
        /// <returns></returns>
        public static string QueryIMDYieldDetails(TrackingCombineSnEntity entity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@WO",SqlDbType.NVarChar,50),
                new SqlParameter("@Station",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@Source",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000)
                };
                sqlParameters[0].Value = entity.PN;
                sqlParameters[1].Value = entity.WO;
                sqlParameters[2].Value = entity.Station ?? "";
                sqlParameters[3].Value = entity.Actor ?? "";
                sqlParameters[4].Value = entity.IMDInfo.Source ?? "";
                sqlParameters[5].Value = entity.StartTime ?? "";
                sqlParameters[6].Value = entity.StopTime ?? "";
                sqlParameters[7].Value = entity.TestSequence ?? "";
                sqlParameters[8].Direction = ParameterDirection.Output;
                sqlParameters[9].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procQueryIMDYieldDetails", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        public static string QueryIMDReports(TrackingCombineSnEntity entity, out DataTable dt)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@SN",SqlDbType.NVarChar,50),
                new SqlParameter("@PN",SqlDbType.NVarChar,50),
                new SqlParameter("@WO",SqlDbType.NVarChar,50),
                new SqlParameter("@Actor",SqlDbType.NVarChar,50),
                new SqlParameter("@Source",SqlDbType.NVarChar,50),
                new SqlParameter("@StartTime",SqlDbType.NVarChar,50),
                new SqlParameter("@StopTime",SqlDbType.NVarChar,50),
                new SqlParameter("@Sequence",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000)
                };
                sqlParameters[0].Value = entity.Sn;
                sqlParameters[1].Value = entity.PN;
                sqlParameters[2].Value = entity.WO;
                sqlParameters[3].Value = entity.Actor ?? "";
                sqlParameters[4].Value = entity.IMDInfo.Source ?? "";
                sqlParameters[5].Value = entity.StartTime ?? "";
                sqlParameters[6].Value = entity.StopTime ?? "";
                sqlParameters[7].Value = entity.TestSequence ?? "";
                sqlParameters[8].Direction = ParameterDirection.Output;
                sqlParameters[9].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedureAndReturnDatatable("procGenerateIMDReport", sqlParameters, out dt);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 验证出货(Ship)工站输入的信息
        /// </summary>
        /// <param name="SN">序列号</param>
        /// <returns></returns>
        public static string VerifyShipWorkStation(string SN)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@Sn",SqlDbType.NVarChar,200),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,2),
                  new SqlParameter("@StateMsg",SqlDbType.NVarChar,4000)
                };
                sqlParameters[0].Value = SN;
                sqlParameters[1].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[2].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedure("procVerifyShipWorkStation", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 检查是否包含IMD测试工站信息《作为Ship工站生成测试报告时是否添加IMD基础信息的判断条件》
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <returns></returns>
        public static bool IsContainsIMDTestStation(string sn)
        {
            StringBuilder sql = new StringBuilder();//查询语句
            DataTable dt = new DataTable();
            try
            {
                sql.AppendFormat("select r.PN, r.Flow, r.Station from vw_SN s with(nolock) inner join WO w on s.WO = w.WO" +
                    " inner join vw_Routing r with(nolock) on w.Flow = r.Flow where s.Sn = '{0}'", sn);
                dt = sqlHelper.GetTable(sql.ToString());
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    //用于判断测试工站是否是IMD但不是IMDOBA站位
                    if (dt.Rows[i]["Station"].ToString().Contains("IMD") && !dt.Rows[i]["Station"].ToString().Contains("OBA"))
                    {
                        return true;
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return false;
        }

        /// <summary>
        /// 序列号是否已经出货
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <returns></returns>
        public static bool IsShiped(string sn)
        {
            StringBuilder sql = new StringBuilder();
            try
            {
                sql.AppendFormat("select count(1) from vw_tracking with(nolock) where Sn='{0}' and Station='{1}'", sn, "SHIP");
                return sqlHelper.ExecuteScalar<int>(sql.ToString()) > 0 ? true : false;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 序列化XML文件
        /// </summary>
        /// <param name="path">the path to save the xml file</param>
        /// <param name="obj">the object you want to serialize</param>
        public static void SerializeToXml<T>(string path, T obj) where T : class
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            string content = string.Empty;
            //serialize
            using (StringWriter writer = new StringWriter())
            {
                serializer.Serialize(writer, obj);
                content = writer.ToString();
            }
            //save to file
            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Read))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.Write(content);
                }
            }
        }

        /// <summary>
        /// 反序列XML文件
        /// </summary>
        /// <param name="path">the path of the xml file</param>
        /// <param name="object_type">the object type you want to deserialize</param>
        public static T DeserializeFromXml<T>(string path) where T : class
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (StreamReader reader = new StreamReader(path))
            {
                return serializer.Deserialize(reader) as T;
            }
        }

        #region Excel导入

        /// <summary>
        /// 从Excel取数据并记录到List集合里
        /// </summary>
        /// <param name="cellHeader">单元头的值和名称：{ { "UserName", "姓名" }, { "Age", "年龄" } };</param>
        /// <param name="filePath">保存文件绝对路径</param>
        /// <param name="errorMsg">错误信息</param>
        /// <param name="startIndex">数据行开始序列，默认为2（即第二列，从0开始）</param>
        /// <returns>转换后的List对象集合</returns>
        public static List<T> ExcelToEntityList<T>(Dictionary<string, string> cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 2) where T : new()
        {
            List<T> enlist = new List<T>();
            errorMsg = new StringBuilder();
            try
            {
                if (Regex.IsMatch(filePath, ".xls$")) // 2003
                {
                    enlist = Excel2003ToEntityList<T>(cellHeader, filePath, out errorMsg, startIndex);
                }
                else if (Regex.IsMatch(filePath, ".xlsx$")) // 2007
                {
                    enlist = Excel2007ToEntityList<T>(cellHeader, filePath, out errorMsg, startIndex);
                }
                return enlist;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 验证模板标题和数据行上限
        /// </summary>
        /// <param name="cellHeader">单元头的值和名称：{ { "UserName", "姓名" }, { "Age", "年龄" } };</param>
        /// <param name="filePath">保存文件绝对路径</param>
        /// <param name="errorMsg">错误信息</param>
        /// <param name="headerStartRowIndex">标题行开始序列，默认为1（即第二列，从0开始）</param>
        /// <returns></returns>
        public static bool VerifyExcelTemplateHeaderAndDataUpperLimit(Dictionary<string, string> cellHeader, string filePath, out StringBuilder errorMsg, int headerStartRowIndex = 1)
        {
            errorMsg = new StringBuilder();
            using (FileStream fs = File.OpenRead(filePath))
            {
                if (Regex.IsMatch(filePath, ".xls$")) // 2003
                {
                    HSSFWorkbook workbook = new HSSFWorkbook(fs);
                    HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    IRow row = sheet.GetRow(headerStartRowIndex);
                    if (row == null)
                    {
                        errorMsg.Append("模板标题行不存在,请检查模板下载的是否正确？");
                        return false;
                    }
                    List<string> lstHeaderCn = cellHeader.Values.ToList();
                    for (int i = 0; i < lstHeaderCn.Count; i++)
                    {
                        if (row.GetCell(i).ToString() != lstHeaderCn[i])
                        {
                            errorMsg.Append("模板标题行以下列顺序排列,请检查模板是否正确?");
                            return false;
                        }
                    }
                    if (sheet.LastRowNum + 1 - 2 == 0)
                    {
                        errorMsg.Append("没有添加数据!");
                        return false;
                    }
                    for (int i = 2; i <= sheet.LastRowNum; i++)
                    {
                        IRow row1 = sheet.GetRow(i);
                        if (row1 == null)
                        {
                            errorMsg.Append(string.Format("第【{0}】行数据为空", i + 1));
                            return false;
                        }
                    }
                    if (sheet.LastRowNum - 2 > 3000)
                    {
                        errorMsg.Append("单次最多导入3000行数据!");
                        return false;
                    }
                }
                else if (Regex.IsMatch(filePath, ".xlsx$")) // 2007
                {
                    XSSFWorkbook workbook = new XSSFWorkbook(fs);
                    XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    IRow row = sheet.GetRow(headerStartRowIndex);
                    if (row == null)
                    {
                        errorMsg.Append("模板标题行不存在,请检查模板下载的是否正确？");
                        return false;
                    }
                    List<string> lstHeaderCn = cellHeader.Values.ToList();
                    for (int i = 0; i < lstHeaderCn.Count; i++)
                    {
                        string a = row.GetCell(i).ToString();
                        if (row.GetCell(i).ToString() != lstHeaderCn[i])
                        {
                            errorMsg.Append("模板标题行排列顺序不正确，请以下列顺序为准【" + string.Join("|", lstHeaderCn.ToArray()) + "】,请检查模板是否正确?");
                            return false;
                        }
                    }

                    if (sheet.LastRowNum + 1 - 2 == 0)
                    {
                        errorMsg.Append("没有添加数据!");
                        return false;
                    }
                    for (int i = 2; i <= sheet.LastRowNum; i++)
                    {
                        IRow row1 = sheet.GetRow(i);
                        if (row1 == null)
                        {
                            errorMsg.Append(string.Format("第【{0}】行数据为空", i + 1));
                            return false;
                        }
                    }
                    if (sheet.LastRowNum + 1 - 2 > 3000)
                    {
                        errorMsg.Append("单次最多导入3000行数据!");
                        return false;
                    }
                }
            }
            return true;
        }

        /// <summary>
        /// 从Excel2003取数据并记录到List集合里
        /// </summary>
        /// <param name="cellHeader">单元头的Key和Value：{ { "UserName", "姓名" }, { "Age", "年龄" } };</param>
        /// <param name="filePath">保存文件绝对路径</param>
        /// <param name="errorMsg">错误信息</param>
        /// <returns>转换好的List对象集合</returns>
        private static List<T> Excel2003ToEntityList<T>(Dictionary<string, string> cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new()
        {
            errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时，会有格式的错误信息
            List<T> enlist = new List<T>(); // 转换后的集合
            try
            {
                using (FileStream fs = File.OpenRead(filePath))
                {
                    HSSFWorkbook workbook = new HSSFWorkbook(fs);
                    HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++)
                    {
                        // 1.判断当前行是否空行，若空行就不在进行读取下一行操作，结束Excel读取操作
                        IRow row = sheet.GetRow(rowIndex);
                        if (row == null)
                        {
                            break;
                        }
                        // 2.每一个Excel row转换为一个实体对象
                        T en = new T();
                        ExcelRowToEntity<T>(cellHeader, row, rowIndex, en, ref errorMsg);

                        enlist.Add(en);
                    }
                }
                return enlist;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw ex;
            }
        }

        /// <summary>
        /// 从Excel2007取数据并记录到List集合里
        /// </summary>
        /// <param name="cellHeader">单元头的Key和Value：{ { "UserName", "姓名" }, { "Age", "年龄" } };</param>
        /// <param name="filePath">保存文件绝对路径</param>
        /// <param name="errorMsg">错误信息</param>
        /// <param name="startIndex">数据行开始序列，默认为2（即第二列，从0开始）</param>
        /// <returns>转换好的List对象集合</returns>
        private static List<T> Excel2007ToEntityList<T>(Dictionary<string, string> cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 2) where T : new()
        {
            errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时，会有格式的错误信息
            List<T> enlist = new List<T>(); // 转换后的集合
            try
            {
                using (FileStream fs = File.OpenRead(filePath))
                {
                    XSSFWorkbook workbook = new XSSFWorkbook(fs);
                    XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页
                    //判断有没有数据
                    if (sheet.LastRowNum < startIndex)
                    {
                        errorMsg.AppendLine("表格中没有数据");
                        return enlist;
                    }
                    for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++)
                    {
                        // 1.判断当前行是否空行，若空行就不在进行读取下一行操作，结束Excel读取操作
                        IRow row = sheet.GetRow(rowIndex);
                        if (row == null)
                        {
                            break;
                        }
                        // 2.每一个Excel row转换为一个实体对象
                        T en = new T();
                        var result = ExcelRowToEntity<T>(cellHeader, row, rowIndex, en, ref errorMsg);
                        if (result)
                            enlist.Add(en);
                    }
                }
                return enlist;
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw ex;
            }
        }

        /// <summary>
        /// Excel row转换为实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cellHeader">单元头的Key和Value：{ { "UserName", "姓名" }, { "Age", "年龄" } };</param>
        /// <param name="row">Excel row</param>
        /// <param name="rowIndex">row index</param>
        /// <param name="en">实体</param>
        /// <param name="errorMsg">错误信息</param>
        private static bool ExcelRowToEntity<T>(Dictionary<string, string> cellHeader, IRow row, int rowIndex, T en, ref StringBuilder errorMsg)
        {
            List<string> keys = cellHeader.Keys.ToList(); // 要赋值的实体对象属性名称
            string errStr = ""; // 当前行转换时，是否有错误信息，格式为：第1行数据转换异常：XXX列；
            for (int i = 0; i < keys.Count; i++)
            {
                // 1.若属性头的名称包含'.',就表示是子类里的属性，那么就要遍历子类，eg：UserEn.TrueName
                if (keys[i].IndexOf(".") >= 0)
                {
                    // 1)解析子类属性
                    string[] properotyArray = keys[i].Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries);
                    string subClassName = properotyArray[0]; // '.'前面的为子类的名称
                    string subClassProperotyName = properotyArray[1]; // '.'后面的为子类的属性名称
                    System.Reflection.PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型
                    if (subClassInfo != null)
                    {
                        // 2)获取子类的实例
                        var subClassEn = en.GetType().GetProperty(subClassName).GetValue(en, null);
                        // 3)根据属性名称获取子类里的属性信息
                        System.Reflection.PropertyInfo properotyInfo = subClassInfo.PropertyType.GetProperty(subClassProperotyName);
                        if (properotyInfo != null)
                        {
                            try
                            {
                                // Excel单元格的值转换为对象属性的值，若类型不对，记录出错信息
                                properotyInfo.SetValue(subClassEn, GetExcelCellToProperty(properotyInfo.PropertyType, row.GetCell(i)), null);
                            }
                            catch (Exception e)
                            {
                                if (errStr.Length == 0)
                                {
                                    errStr = "第" + rowIndex + "行数据转换异常：";
                                }
                                errStr += cellHeader[keys[i]] + "列；";
                            }
                        }
                    }
                }
                else
                {
                    // 2.给指定的属性赋值
                    System.Reflection.PropertyInfo properotyInfo = en.GetType().GetProperty(keys[i]);

                    if (properotyInfo != null)
                    {
                        try
                        {
                            bool valideResult = true; //验证的结果
                            //获取属性上的自定义特性
                            if (properotyInfo.IsDefined(typeof(BaseValidateAttribute), true))
                            {
                                foreach (BaseValidateAttribute attr in properotyInfo.GetCustomAttributes(typeof(BaseValidateAttribute), true))
                                {
                                    if (!attr.Validate(row.GetCell(i)))
                                    {
                                        valideResult = false;
                                        errStr += "第" + (rowIndex + 1) + "行 【" + cellHeader[keys[i]] + "】列 数据不符合规范,规范是【" + attr.Description + "】\r\n";
                                        break;
                                    }
                                }
                            }
                            if (valideResult)
                            {
                                // Excel单元格的值转换为对象属性的值，若类型不对，记录出错信息
                                properotyInfo.SetValue(en, GetExcelCellToProperty(properotyInfo.PropertyType, row.GetCell(i)), null);
                            }
                        }
                        catch (Exception e)
                        {
                            if (errStr.Length == 0)
                            {
                                errStr = "第" + (rowIndex + 1) + "行数据转换异常：";
                            }
                            errStr += cellHeader[keys[i]] + "列；\r\n";
                        }
                    }
                }
            }
            // 若有错误信息，就添加到错误信息里
            if (errStr.Length > 0)
            {
                errorMsg.AppendLine(errStr);
                return false;
            }
            else
                return true;
        }

        /// <summary>
        /// Excel Cell转换为实体的属性值
        /// </summary>
        /// <param name="distanceType">目标对象类型</param>
        /// <param name="sourceCell">对象属性的值</param>
        private static Object GetExcelCellToProperty(Type distanceType, ICell sourceCell)
        {
            object rs = distanceType.IsValueType ? Activator.CreateInstance(distanceType) : null;

            // 1.判断传递的单元格是否为空
            if (sourceCell == null || string.IsNullOrEmpty(sourceCell.ToString()))
            {
                return rs;
            }

            // 2.Excel文本和数字单元格转换，在Excel里文本和数字是不能进行转换，所以这里预先存值
            object sourceValue = null;
            switch (sourceCell.CellType)
            {
                case CellType.Blank:
                    break;

                case CellType.Boolean:
                    break;

                case CellType.Error:
                    break;

                case CellType.Formula:
                    break;

                case CellType.Numeric:
                    sourceValue = sourceCell.NumericCellValue;
                    break;

                case CellType.String:
                    sourceValue = sourceCell.StringCellValue;
                    break;

                case CellType.Unknown:
                    break;

                default:
                    break;
            }

            string valueDataType = distanceType.Name;

            // 在这里进行特定类型的处理
            switch (valueDataType.ToLower()) // 以防出错，全部小写
            {
                case "string":
                    rs = sourceValue.ToString();
                    break;

                case "int":
                case "int16":
                case "int32":
                    rs = (int)Convert.ChangeType(sourceCell.NumericCellValue.ToString(), distanceType);
                    break;

                case "float":
                case "single":
                    rs = (float)Convert.ChangeType(sourceCell.NumericCellValue.ToString(), distanceType);
                    break;

                case "datetime":
                    rs = sourceCell.DateCellValue;
                    break;

                case "guid":
                    rs = (Guid)Convert.ChangeType(sourceCell.NumericCellValue.ToString(), distanceType);
                    return rs;
            }
            return rs;
        }

        #endregion Excel导入

        /// <summary>
        /// 将数据库表转换成实体类
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="sql">查询语句</param>
        /// <returns></returns>
        public static List<T> SqlTableToEntityConvert<T>(string sql) where T : class
        {
            DataTable dtSource = new DataTable();
            List<T> entities = new List<T>();
            try
            {
                dtSource = sqlHelper.GetTable(sql);
                for (int i = 0; i < dtSource.Rows.Count; i++)
                {
                    Type t = typeof(T);
                    object entity = Activator.CreateInstance(t);
                    var propertyInfos = t.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
                    foreach (var p in propertyInfos)
                    {
                        string propertyName = p.Name; //属性名称
                        Type propertyType = p.PropertyType;
                        if (dtSource.Columns.Contains(propertyName))
                        {
                            var propertyVal = Convert.ChangeType(dtSource.Rows[i][propertyName].ToString(), propertyType);
                            p.SetValue(entity, propertyVal);
                        }
                    }
                    entities.Add((T)entity);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return entities;
        }

        /// <summary>
        /// list实体对象转DataTable
        /// </summary>
        /// <typeparam name="T">实体</typeparam>
        /// <param name="list">实体集合</param>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        public static DataTable ListToDatatableConvert<T>(IEnumerable<T> list, string tableName)
        {
            DataTable dtResult = new DataTable();
            dtResult.TableName = tableName;
            List<PropertyInfo> propertiyInfos = new List<PropertyInfo>();
            //生成各列
            foreach (var p in typeof(T).GetProperties())
            {
                propertiyInfos.Add(p);
                dtResult.Columns.Add(p.Name, p.PropertyType);
            }
            //生成各行
            foreach (var item in list)
            {
                if (item == null)
                {
                    continue;
                }
                DataRow dataRow = dtResult.NewRow();
                propertiyInfos.ForEach(p => dataRow[p.Name] = p.GetValue(item, null));
                dtResult.Rows.Add(dataRow);
            }
            return dtResult;
        }

        /// <summary>
        /// 查询工单是否已经生产
        /// </summary>
        /// <param name="WO">工单</param>
        /// <returns></returns>
        public static bool WOIsProduced(string WO)
        {
            StringBuilder sql = new StringBuilder();
            try
            {
                sql.AppendFormat("select count(1) from [dbo].[vw_Tracking] with(nolock) where wo='{0}'", WO);
                return sqlHelper.ExecuteScalar<int>(sql.ToString()) > 0 ? true : false; //大于零表示已经有生产记录，小于等于零表示没有生产记录
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 删除工单
        /// </summary>
        /// <param name="entity">工单实体</param>
        /// <returns></returns>
        public static string DeleteWOInfo(WOEntity entity)
        {
            string retMsg = string.Empty;//数据库返回的状态信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                new SqlParameter("@WO",SqlDbType.NVarChar,50),
                new SqlParameter("@StateCode",SqlDbType.NVarChar,10),
                new SqlParameter("@StateMsg",SqlDbType.NVarChar,1000)
                };
                sqlParameters[0].Value = entity.WO ?? "";
                sqlParameters[1].Direction = ParameterDirection.Output;
                sqlParameters[2].Direction = ParameterDirection.Output;
                retMsg = sqlHelper.ExecuteStoredProcedure("procDeleteWO", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }

        /// <summary>
        /// 查询序列号格式在系统中是否存在
        /// </summary>
        /// <param name="format">序列号格式</param>
        /// <returns></returns>
        public static bool IsSnFormatExists(string format)
        {
            StringBuilder sql = new StringBuilder();
            try
            {
                sql.AppendFormat("select count(1) from PN where SnFormat='{0}'", format);
                int records = sqlHelper.ExecuteScalar<int>(sql.ToString());
                if (records > 0)
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return false;
        }

        /// <summary>
        /// 添加内容到csv文件
        /// </summary>
        /// <typeparam name="T">内容类型</typeparam>
        /// <param name="path">csv文件路径</param>
        /// <param name="content">内容</param>
        public static void AddContentToCsv<T>(string path, T content)
        {
            using (var sw = new StreamWriter(path, true, Encoding.UTF8))
            {
                var paramType = typeof(T);
                if (paramType.Equals(typeof(string)))
                {
                    sw.WriteLine(content.ToString());
                }
                else if (paramType.Equals(typeof(string[])))
                {
                    sw.WriteLine(string.Join(",", (string[])Convert.ChangeType(content, typeof(string[]))));
                }
            }
        }
        /// <summary>
        /// 通过命令行关闭进程
        /// </summary>
        /// <param name="processName">进程名称</param>
        /// <returns></returns>
        public static bool CloseProcessByCommandLine(string processName)
        {
            try
            {
                // 构造命令行字符串
                string command = $"/C taskkill /IM {processName}.exe /F";
                // 创建一个新的 ProcessStartInfo 实例，配置命令行参数
                ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd.exe", command)
                {
                    CreateNoWindow = true,  // 不显示命令行窗口
                    UseShellExecute = false, // 不使用外壳执行
                    RedirectStandardOutput = true,  // 重定向标准输出
                    RedirectStandardError = true  // 重定向标准错误输出
                };
                // 启动命令行进程
                Process process = Process.Start(processStartInfo);
                // 读取命令执行的输出信息
                string output = process.StandardOutput.ReadToEnd();
                string error = process.StandardError.ReadToEnd();
                // 等待命令执行完成
                process.WaitForExit();
                if (!string.IsNullOrEmpty(error))
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                return false;
            }
            return true;
        }
        /// <summary>
        /// 获取机种标签打印参数
        /// </summary>
        /// <param name="pn">机种</param>
        /// <param name="printType">打印类型<Label/Packing></param>
        /// <returns></returns>
        public static DataTable GetLabelConfigByPartNumber(string pn,string printType="Label")
        {
            var sql = new StringBuilder();
            var dtSource = new DataTable();
            try
            {
                sql.AppendFormat("select p.PartNumber,p.PrintCopiesNum, p.SnFormat," +
                                 "t.TemplateName, t.VariableNum, t.TemplateType, t.Size,"+
                                 "tv.VariableName, isnull(ptv.VariableValue, '') VariableValue "+
                                 "from PN p join PNTemplate pt on p.PartNumber = pt.PN "+
                                           "join Template t on pt.TemplateId = t.Id "+
                                           "join LabelTemplateVariable ltv on ltv.TemplateId = t.Id "+
                                           "join TemplateVariable tv on ltv.VariableId = tv.Id "+
                                      "left join PNTemplateVariable ptv on ptv.VariableId = tv.Id and ptv.TemplateId = t.Id and ptv.PN = pt.PN "+
                                 "where t.TemplateType = '{0}' and p.PartNumber = '{1}'",printType,pn);
                dtSource=sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtSource;
        }
        /// <summary>
        ///  通过模版获取模版和模版变量之间的关系
        /// </summary>
        /// <param name="templateName">模版名称</param>
        /// <returns></returns>
        public static DataTable GetLabelTemplateVariableMapByTemplate(string templateName)
        {
            var sql = new StringBuilder();
            var dtSource = new DataTable();
            try
            {
                sql.AppendFormat("select t.TemplateName, tv.VariableName "+
                                 "from Template t join LabelTemplateVariable ltv on t.id = ltv.TemplateId "+
                                                 "join TemplateVariable tv on ltv.VariableId = tv.Id "+

                                 "where t.TemplateName = '{0}'", templateName);
                dtSource = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtSource;
        }
        /// <summary>
        /// 获取机种模版变量之间的关系
        /// </summary>
        /// <param name="pn">机种</param>
        /// <param name="template">模版</param>
        /// <param name="templateType">模版类型</param>
        /// <returns></returns>
        public static DataTable GetPartNumberTemplateVariable(string pn,string template,string templateType)
        {
            var sql = new StringBuilder();
            var dtSource = new DataTable();
            try
            {
                sql.AppendFormat("select ptv.PN,t.TemplateName,tv.VariableName,ptv.VariableValue "+
                                 "from Template t join PNTemplateVariable ptv on t.Id = ptv.TemplateId "+
                                                 "join TemplateVariable tv on tv.Id = ptv.VariableId "+
                                 "where t.TemplateType = '{0}' and ptv.PN = '{1}' and t.TemplateName = '{2}'", templateType,pn,template);
                dtSource = sqlHelper.GetTable(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return dtSource;
        }
        /// <summary>
        /// 添加标签配置信息
        /// </summary>
        /// <param name="strConfig">配置信息字符串《PN1,TEMPLATE1,VAR1,VARVALUE1|PN2,TEMPLATE2,VAR2,VARVALUE2...》</param>
        /// <returns></returns>
        public static string AddLabelConfigInfos(string strConfig)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@ConfigString",SqlDbType.NVarChar,-1),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                  new SqlParameter("@StateMsg",SqlDbType.VarChar,500)
                };
                sqlParameters[0].Value = strConfig;
                sqlParameters[1].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[2].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedure("procAddLabelConfigInfos", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }
        /// <summary>
        /// 添加模版、变量对应关系
        /// </summary>
        /// <param name="strConfig">配置信息</param>
        /// <returns></returns>
        public static string AddTemplateVariableMap(string strConfig)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@strTempVar",SqlDbType.NVarChar,-1),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                  new SqlParameter("@StateMsg",SqlDbType.VarChar,500)
                };
                sqlParameters[0].Value = strConfig;
                sqlParameters[1].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[2].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedure("procAddTemplateVariableMap", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }
        /// <summary>
        /// 测试记录作废
        /// </summary>
        /// <param name="sn">序列号</param>
        /// <param name="obsoleteReason">作废原因</param>
        /// <param name="obsoleteActor">作废工号</param>
        /// <returns></returns>
        public static string TestTrackingObsolete(string sn,string obsoleteReason,string obsoleteActor)
        {
            string retMsg = string.Empty;//数据库返回的信息
            SqlParameter[] sqlParameters = null;
            try
            {
                sqlParameters = new SqlParameter[] {
                  new SqlParameter("@Sn",SqlDbType.NVarChar,50),
                  new SqlParameter("@ObsoleteReason",SqlDbType.NVarChar,50),
                  new SqlParameter("@ObsoleteActor",SqlDbType.NVarChar,50),
                  new SqlParameter("@StateCode",SqlDbType.VarChar,10),
                  new SqlParameter("@StateMsg",SqlDbType.VarChar,500)
                };
                sqlParameters[0].Value = sn;
                sqlParameters[1].Value = obsoleteReason;
                sqlParameters[2].Value = obsoleteActor;
                sqlParameters[3].Direction = ParameterDirection.Output; //StateCode
                sqlParameters[4].Direction = ParameterDirection.Output; //StateMsg
                retMsg = sqlHelper.ExecuteStoredProcedure("procDeleteTestTrackingAndBackup", sqlParameters);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
            return retMsg;
        }
        /// <summary>
        /// 添加打印日志
        /// </summary>
        /// <param name="content">打印内容</param>
        /// <param name="printerName">打印机名称</param>
        /// <param name="printType">打印类型《Label/Packing》</param>
        /// <param name="isReprint">是否补打</param>
        /// <param name="remarks">备注</param>
        public static void RecordPrintLog(string content, byte isReprint = 0,string printType="Label", string printerName = "",string remarks="")
        {
            var sql = new StringBuilder();
            try
            {
                sql.AppendFormat($"insert into PrintLog values('{content}','{printType}','{isReprint}','{LogInInfo.User}','{Environment.MachineName}','{printerName}',getdate(),'{remarks}')");
                sqlHelper.ExecuteNonQuery(sql.ToString());
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }
    }
}